﻿using HalconDotNet;
using Halcon二次开发.Controller.Controller基类;
using Halcon二次开发.Model.储存每个Controller的单例对象;
using Halcon二次开发.Model.工具区域的扩展类;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using Halcon二次开发.Model;
using System.Windows.Forms;
using Halcon二次开发.View.找圆_线_矩形;
using Halcon二次开发.Model.储放所有单例.储存每个单例界面;
using System.Windows.Shapes;
using System.Windows.Media;
using static System.Windows.Forms.LinkLabel;
using Halcon二次开发.Tools;
using Halcon二次开发.Controller.数据加载与保存;
using System.IO;
using Halcon二次开发.Model.自定义控件;

namespace Halcon二次开发.Controller.画线工具交互
{
    public class FindLineToolController
    {
        string path;
        int index = 0;
        /// <summary>
        /// 该工具的线段对象
        /// </summary>
        List<HDrawingObjectEx> lines = new List<HDrawingObjectEx>();
        /// <summary>
        /// 当前控件对象
        /// </summary>
        public HSmartWindowControl hw;

        /// 移动事件更改数据禁止
        /// </summary>
        bool check = false;

        /// <summary>
        /// 界面
        /// </summary>
        H_FindLineToolForm form;

        public HwindowFlowNodeUrseControl HwindowFlowNode;

        public FindLineToolController(HwindowFlowNodeUrseControl HwindowFlowNode, H_FindLineToolForm form,string path, NumericUpDown numericUpDown1, NumericUpDown numericUpDown2, NumericUpDown numericUpDown3, NumericUpDown numericUpDown4)
        {
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            //获取当前工位
            hw = HwindowFlowNode.hSmartWindowControl1;
            this.form = form;
            //读取模板信息
            HelpJsons.Read<HTuple>("");
            this.path = path;

            this.numericUpDown1 = numericUpDown1;
            this.numericUpDown2 = numericUpDown2;
            this.numericUpDown3 = numericUpDown3;
            this.numericUpDown4 = numericUpDown4;

        }
        /// <summary>
        /// 偏移量 - 第一个模板的数据  第一个绘制的线段数据 
        /// </summary>
        public List<double> model1;
        public HTuple[] firstLine = new HTuple[4];
        public bool linePaper = true;
        #region 该控件的参数值
        /// <summary>
        /// 当前图像对象
        /// </summary>
        public HObject HideIntputImage;
        /// <summary>
        /// 卡尺的位置
        /// </summary>
        NumericUpDown numericUpDown1, numericUpDown2, numericUpDown3, numericUpDown4;
        /// <summary>
        /// 放置多卡尺 *
        /// </summary>
        public double[] HideIntputArrayColumns, HideIntputArrayRows, HideIntputArrayPhis;
        /// <summary>
        /// 卡尺的位置   
        /// </summary>
        public double HideIntputX1, HideIntputY1, HideIntputX2, HideIntputY2, HideOutputX1, HideOutputY1, HideOutputX2, HideOutputY2 ;
        public double[] HideOutputArrayRows, HideOutputArrayColumns, HideOutputArrayDistances;
        /// <summary>
        /// 卡尺的宽度,高度,对比度,平滑度
        /// </summary>
        public double HideIntputWidth = 0, HideIntputHeight = 0, HideIntputThreshold, HideIntputSigma;
        /// <summary>
        /// 颜色样式
        /// </summary>
        public string HideOutputBorderColor, HideOutputCenterConlor, HideOutputlineColor = "red";
        /// <summary>
        /// 抓边成功
        /// </summary>
        public bool OK = false;
        /// <summary>
        /// 卡尺数量
        /// </summary>
        public int CaliperNumber = 10;


        #endregion

        /// <summary>
        /// 创建一条线
        /// </summary>
        public void DrawLine(NumericUpDown numericUpDown1, NumericUpDown numericUpDown2, NumericUpDown numericUpDown3, NumericUpDown numericUpDown4,
            NumericUpDown numericUpDown8, NumericUpDown numericUpDown9, NumericUpDown numericUpDown6, NumericUpDown numericUpDown5, TextBox textBox1, TextBox textBox2,
            TextBox textBox3)
        {
            HideOutputlineColor = textBox3.Text;
            //放置线条就不用再次放置了

            if (HideIntputImage == null)
            {
                throw new Exception("当前图像为空!");
            }
            if (OK) return;
            OK = true;
            ClearObject();
            //定义绘制线的开始坐标与结束坐标
            var lineTuple = new HTuple[] { 0, 0, 0, 150 };
            //创建线的对象
            HDrawingObject lineObj = HDrawingObject.CreateDrawingObject(HDrawingObject.HDrawingObjectType.LINE, lineTuple);

            //设置线的颜色
            try
            {
                lineObj.SetDrawingObjectParams("color", HideOutputlineColor.ToLower());
            }
            catch
            {
                lineObj.SetDrawingObjectParams("color", "red");
                throw new Exception("该线条不支持此颜色以为你选择默认颜色!");
            }

            //这里要标注区域
            if (HideIntputArrayRows != null && HideIntputArrayRows.Length > 0)
            {
                HOperatorSet.SetColor(hw.HalconWindow, "red");
                HOperatorSet.SetDraw(hw.HalconWindow, "fill");
                HOperatorSet.GenCircle(out HObject ho_Biaozhu, HideIntputArrayRows[0], HideIntputArrayColumns[0], 20);
                HOperatorSet.DispObj(ho_Biaozhu, hw.HalconWindow);
                HOperatorSet.SetColor(hw.HalconWindow, HideOutputlineColor.ToLower());
                HOperatorSet.SetDraw(hw.HalconWindow, "margin");
            }

            //线段拖动触发事件注册
            lineObj.OnDrag(LineOnDrag);
            //线段长度修改触发事件注册
            lineObj.OnResize(LineOnResize);

            //永久保留该对象,不然会被垃圾回收机制回收
            lines.Add(new HDrawingObjectEx
            {
                HDrawingObject = lineObj,
                hTuples = lineTuple
            });
            //增加这个对象到指定Halcon窗口
            hw.HalconWindow.AttachDrawingObjectToWindow(lineObj);

            HideIntputX1 = double.Parse(numericUpDown1.Value + "");
            HideIntputY1 = double.Parse(numericUpDown2.Value + "");
            HideIntputX2 = double.Parse(numericUpDown3.Value + "");
            HideIntputY2 = double.Parse(numericUpDown4.Value + "");

            this.numericUpDown1 = numericUpDown1;
            this.numericUpDown2 = numericUpDown2;
            this.numericUpDown3 = numericUpDown3;
            this.numericUpDown4 = numericUpDown4;

            this.HideIntputThreshold = double.Parse(numericUpDown8.Value + "");
            this.HideIntputSigma = double.Parse(numericUpDown9.Value + "");
            this.HideIntputHeight = double.Parse(numericUpDown5.Value + "");
            this.HideIntputWidth = double.Parse(numericUpDown6.Value + "");
            this.HideOutputBorderColor = textBox1.Text;
            this.HideOutputCenterConlor = textBox2.Text;
            this.HideOutputlineColor = textBox3.Text;
            if (!PMAIsNg())
            {
                model1 = new List<double>();
                //第一个模板数据  
                model1.Add(HideIntputArrayRows[0]);
                model1.Add(HideIntputArrayColumns[0]);
                model1.Add(HideIntputArrayPhis[0]);
                SetModelPaths();
                //重绘线段时记录第一个线段对象
                linePaper = true;
            }
        }
            /// <summary>
            /// 线段拖动触发事件
            /// </summary>
            /// <param name="drawid"></param>
            /// <param name="window"></param>
            /// <param name="type"></param>
        public void LineOnDrag(HDrawingObject drawid, HWindow window, string type)
        {
            UpdataDrawingObjecData(drawid);
        }
        /// <summary>
        /// 线段长度修改触发事件
        /// </summary>
        /// <param name="drawid"></param>
        /// <param name="window"></param>
        /// <param name="type"></param>
        public void LineOnResize(HDrawingObject drawid, HWindow window, string type)
        {
            try
            {
                UpdataDrawingObjecData(drawid);
            }
            catch
            {

            }
        }
        /// <summary>
        /// 线段拖动修改长度方法
        /// </summary>
        /// <param name="drawid"></param>
        public void UpdataDrawingObjecData(HDrawingObject drawid)
        {
            check = true;
            //创建一个要得到对象属性的元组
            var attTuple = new HTuple("row1", "column1", "row2", "column2");
            //获取对应的属性
            var valueTuple = drawid.GetDrawingObjectParams(attTuple);
            //对对应的属性进行封装一下,后面好加入到集合中
            var attValues = new HTuple[] { valueTuple[0], valueTuple[1], valueTuple[2], valueTuple[3] };
            //更新数据
            lines[0].hTuples = attValues;
            this.numericUpDown1.Value = decimal.Parse(valueTuple[1].D.ToString());
            this.numericUpDown2.Value = decimal.Parse(valueTuple[0].D.ToString());
            this.numericUpDown3.Value = decimal.Parse(valueTuple[3].D.ToString());
            this.numericUpDown4.Value = decimal.Parse(valueTuple[2].D.ToString());
            //监听
            Debug.WriteLine(valueTuple[0] + " " + valueTuple[1] + " " + valueTuple[2] + " " + valueTuple[3]);
        }

        /// <summary>
        /// 开始抓边
        /// </summary>
        public void Bound_Line()
        {
            if (HideIntputImage == null)
            {
                throw new Exception("当前图像为空");
            }
            
            //清理上次的直线生成出来的轮廓
            ClearObject();
            try
            {
                if (!PMAIsNg())
                {
                    if (HideIntputArrayColumns == null || HideIntputArrayRows == null || HideIntputArrayPhis == null || HideIntputArrayColumns.Length == 0 || HideIntputArrayRows.Length == 0 || HideIntputArrayPhis.Length == 0 || model1 == null)
                    {
                        throw new Exception("无模板区域，无法找线");
                    }
                    else{
                        //绘制所有模板的线段*
                        DrawLines(HideIntputArrayColumns, HideIntputArrayRows, HideIntputArrayPhis);
                    }
                }
                //清理上次结果
                form.dataGridView1.Rows.Clear();
                HideOutputArrayRows = null;
                HideOutputArrayColumns = null;
                HideOutputArrayDistances = null;
                index = 0;
                foreach (HDrawingObjectEx item in lines)
                {
                    //获取线的元组
                    var lineTuple = item.hTuples;
                    var lineParams = new HTuple(lineTuple);
                    HOperatorSet.CreateMetrologyModel(out HTuple hv_MetrologyHandle);
                    //增加一个矩形的计量模型
                    HOperatorSet.AddMetrologyObjectGeneric(hv_MetrologyHandle, "line", lineParams, double.Parse(form.numericUpDown5.Value.ToString()), double.Parse(form.numericUpDown6.Value.ToString()),
                        HideIntputSigma, HideIntputThreshold, new HTuple(), new HTuple(), out HTuple hv_Index);
                    //该参数指定暗/亮或亮/暗边的使用  negative:正极性  positive:负极性  uniform:正负极性只有一个
                    //获取极性
                    string polarity = "";
                    if (form.comboBox1.SelectedItem.ToString() == "全部")
                    {
                        polarity = "all";
                    }
                    if (form.comboBox1.SelectedItem.ToString() == "正极性")
                    {
                        polarity = "negative";
                    }
                    if (form.comboBox1.SelectedItem.ToString() == "负极性")
                    {
                        polarity = "positive";
                    }
                    if (form.comboBox1.SelectedItem.ToString() == "仅有")
                    {
                        polarity = "uniform";
                    }
                    //设置极性
                    HOperatorSet.SetMetrologyObjectParam(hv_MetrologyHandle, "all", "measure_transition", polarity);
                    //卡尺的数量
                    HOperatorSet.SetMetrologyObjectParam(hv_MetrologyHandle, "all", "num_measures", CaliperNumber);
                    //卡尺卡的数量 接受的结果数
                    HOperatorSet.SetMetrologyObjectParam(hv_MetrologyHandle, "all", "num_instances", int.Parse(form.numericUpDown11.Value.ToString()));
                    //bilinear
                    HOperatorSet.SetMetrologyObjectParam(hv_MetrologyHandle, "all", "measure_interpolation", "bicubic");

                    HOperatorSet.SetMetrologyObjectParam(hv_MetrologyHandle, "all", "measure_select", "all");
                    //最小分数
                    HOperatorSet.SetMetrologyObjectParam(hv_MetrologyHandle, "all", "min_score", double.Parse(form.numericUpDown10.Value.ToString()));

                    //开始抓
                    HOperatorSet.ApplyMetrologyModel(HideIntputImage, hv_MetrologyHandle);

                    HOperatorSet.GetMetrologyObjectMeasures(out HObject ho_Contours, hv_MetrologyHandle, "all", "all",
                        out HTuple hv_Row, out HTuple hv_Column);

                    if (hv_Row.Length > 0 && hv_Column.Length > 0)
                    {

                        //得到距离在hv_Parameter中
                        HOperatorSet.GetMetrologyObjectResult(hv_MetrologyHandle, 0, "all", "result_type", "all_param",
                            out HTuple hv_Parameter);
                        //没抓到
                        if (hv_Parameter.Length > 0)
                        {
                            //设置边框颜色
                            HOperatorSet.SetColor(hw.HalconWindow, form.textBox1.Text.ToLower());

                            //显示边框区域
                            HOperatorSet.DispObj(ho_Contours, hw.HalconWindow);

                            HOperatorSet.GetMetrologyObjectResultContour(out HObject ho_Contour, hv_MetrologyHandle, 0, "all", 1.5);
                            //中心线颜色
                            HOperatorSet.SetColor(hw.HalconWindow, HideOutputCenterConlor.ToLower());

                            HOperatorSet.SetLineWidth(hw.HalconWindow, 3);
                            HOperatorSet.DispObj(ho_Contour, hw.HalconWindow);
                            //OK = true;
                            index++;
                            HOperatorSet.DistancePp(hv_Parameter[0], hv_Parameter
                                [1], hv_Parameter[2], hv_Parameter[3], out HTuple distance);
                            //添加结果集
                            form.dataGridView1.Rows.Add(index, hv_Parameter[1] - hv_Parameter[3], hv_Parameter[0] - hv_Parameter[2],distance);
                            HOperatorSet.SetLineWidth(hw.HalconWindow, 1);
                            HideOutputX1 = hv_Parameter[1];
                            HideOutputY1 = hv_Parameter[0];
                            HideOutputX2 = hv_Parameter[3];
                            HideOutputY1 = hv_Parameter[2];
                        }
                        else
                        {
                            continue;
                        }
                    }
                    else
                    {
                        continue;
                    }
                }
                if (index == 0)
                {
                    throw new Exception("找线工具未找到");
                }
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("AddMetrologyObjectGeneric")||ex.Message.Contains("_metrology_object_generic"))
                {

                    throw new Exception("找线工具未找到 请重新匹配模板!");
                }
                else
                {
                    throw new Exception(ex.Message);
                }
            }
            finally
            {
                ClearObject();
                DataGridViewRowCollection rows= form.dataGridView1.Rows;
                HideOutputArrayRows = new double[rows.Count];
                HideOutputArrayColumns = new double[rows.Count];
                HideOutputArrayDistances = new double[rows.Count];
                for (int i = 0; i < rows.Count; i++)
                {
                    HideOutputArrayRows[i] = double.Parse(rows[i].Cells[1].Value.ToString()) ;
                    HideOutputArrayColumns[i] = double.Parse(rows[i].Cells[2].Value.ToString());
                    HideOutputArrayDistances[i] = double.Parse(rows[i].Cells[3].Value.ToString());
                }
            }
        }
        /// <summary>
        /// 清除对象
        /// </summary>
        public void ClearObject()
        {
            if (lines.Count == 0) return;
            foreach (var item in lines)
            {
                var hobject = item.HDrawingObject;
                if (hobject.ID == 0) continue;
                hw.HalconWindow.DetachDrawingObjectFromWindow(hobject);
            }
            OK = false;
        }
        /// <summary>
        /// 打开颜色提取器
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void OpenColorDir(Object sender, EventArgs e)
        {
            ColorDialog dlg = new ColorDialog();
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                string str = dlg.Color.ToString();
                if (!str.Contains('='))
                {
                    str = str.Substring(str.IndexOf('[') + 1, (str.IndexOf(']', str.IndexOf('[')) - str.IndexOf('[')) - 1);
                    (sender as TextBox).Tag = dlg.Color;
                    (sender as TextBox).Text = str;
                }
                else
                {
                    (FormDb.Db["Form1"] as Form1).textBox1.AppendText("该软件不支持RGB!\r\n");
                }
            }
        }
        /// <summary>
        /// shuzhi移动
        /// </summary>
        public void Move_X(double x1, double y1, double x2, double y2)
        {
            //ClearObject();
            //HideIntputX1 = x1;
            //HideIntputY1 = y1;
            //HideIntputX2 = x2;
            //HideIntputY2 = y2;
            ////定义绘制线的开始坐标与结束坐标
            //var lineTuple = new HTuple[] { y1, x1, y2, x2 };
            ////创建线的对象
            //var lineObj = HDrawingObject.CreateDrawingObject(HDrawingObject.HDrawingObjectType.LINE, lineTuple);
            ////线段拖动触发事件注册
            //lineObj.OnDrag(LineOnDrag);
            ////线段长度修改触发事件注册
            //lineObj.OnResize(LineOnResize);

            ////设置线的颜色
            //try
            //{
            //    lineObj.SetDrawingObjectParams("color", HideOutputlineColor.ToLower());
            //}
            //catch
            //{
            //    (FormDb.Db["Form1"] as Form1).textBox1.AppendText("该线条不支持此颜色以为你选择默认颜色!\r\n");
            //    lineObj.SetDrawingObjectParams("color", "red");
            //}

            ////永久保留该对象,不然会被垃圾回收机制回收 
            //lines.Clear();
            //lines.Add(new HDrawingObjectEx
            //{
            //    HDrawingObject = lineObj,
            //    hTuples = lineTuple
            //});
            ////增加这个对象到指定Halcon窗口
            //hw.HalconWindow.AttachDrawingObjectToWindow(lineObj);
        }
        /// <summary>
        /// 更改高度宽度
        /// </summary>
        /// <param name="width"></param>
        /// <param name="heigth"></param>
        public void PushHeightWidth(double width, double heigth)
        {
            this.HideIntputWidth = width;
            this.HideIntputHeight = heigth;
        }
        /// <summary>
        /// 更改对比度平滑度
        /// </summary>
        /// <param name="width"></param>
        /// <param name="heigth"></param>
        public void PushThresholdSigma(double threshold, double sigma)
        {
            this.HideIntputThreshold = threshold;
            this.HideIntputSigma = sigma;
        }

        /// <summary>
        /// 更改颜色样式
        /// </summary>
        public void PushColor(string borderColor, string centerConlor, string lineColor)
        {
            this.HideOutputBorderColor = borderColor;
            this.HideOutputCenterConlor = centerConlor;
            this.HideOutputlineColor = lineColor;
        }
        /// <summary>
        /// 工具运行方法
        /// </summary>
        public void Run()
        {
            GetModelPaths();
            //第一个模板数据  
            Bound_Line();
        }

        /// <summary>
        /// 工具的单次运行
        /// </summary>
        public void Tool_Run()
        {
            if (HideIntputImage == null) return;
            hw.HalconWindow.ClearWindow();
            if (HideIntputImage == null)
            {
                throw new Exception("当前图像为空");
            }
            HOperatorSet.DispObj(HideIntputImage, hw.HalconWindow);
            Run();
        }
        /// <summary>
        /// 卡尺数量更改
        /// </summary>
        /// <param name="caliperMumber"></param>
        public void UpdataCaliperNumber(int caliperMumber)
        {
            this.CaliperNumber = caliperMumber;
        }
        /// <summary>
        /// 模板是否连接
        /// </summary>
        /// <returns></returns>
        public bool PMAIsNg()
        {
            //foreach (TreeNode node in StaicResouce.HwindowFlowNodeUrse.treeView1.Nodes)
            //{
            //    if (node.Nodes.Count == 0) continue;
            //    if (node.Nodes[0].Tag == this && node.Nodes[1].Text.Contains("<—") && node.Nodes[2].Text.Contains("<—") && node.Nodes[3].Text.Contains("<—"))
            //    {
            //        return false;
            //    }
            //}
            return false;
        }
        /// <summary>
        /// 绘制与所有模板匹配的卡尺
        /// </summary>
        /// <param name="IntputColums">所有模板列坐标</param>
        /// <param name="IntputRows"></param>
        /// <param name="IntputAngles"></param>
        public void DrawLines(double[] IntputColums, double[] IntputRows, double[] IntputAngles)
        {
            //创建线的对象
            HOperatorSet.GenRegionLine(out HObject hLine,double.Parse( numericUpDown2.Value.ToString()), double.Parse(numericUpDown1.Value.ToString()), double.Parse(numericUpDown4.Value.ToString()), double.Parse(numericUpDown3.Value.ToString()));
            lines.Clear();
            for (int i = 0; i < IntputColums.Length; i++)
            {
                HObject ho_RegionAffineTrans = UtiyHalcon.MatrixCalculate(hLine, IntputRows[i], IntputColums[i], IntputAngles[i], model1[0], model1[1], model1[2]);
                HOperatorSet.GetRegionPoints(ho_RegionAffineTrans, out HTuple hv_Rows, out HTuple hv_Columns);
                if (hv_Rows.Length==0)
                {
                    continue;
                }
                var lineTuple = new HTuple[] { hv_Rows[0], hv_Columns[0], hv_Rows[hv_Rows.Length - 1], hv_Columns[hv_Columns.Length - 1] };// 提取开始坐标和结束坐标

                HDrawingObject lineObj = HDrawingObject.CreateDrawingObject(HDrawingObject.HDrawingObjectType.LINE, lineTuple);// 绘制线段
                //设置线的颜色
                try
                {
                    lineObj.SetDrawingObjectParams("color", HideOutputlineColor.ToLower());
                }
                catch
                {
                    lineObj.SetDrawingObjectParams("color", "red");
                   // throw new Exception("该线条不支持此颜色以为你选择默认颜色!");
                }
                //永久保留该对象,不然会被垃圾回收机制回收
                lines.Add(new HDrawingObjectEx
                {
                    HDrawingObject = lineObj,
                    hTuples = lineTuple
                });
                //增加这个对象到指定Halcon窗口
                hw.HalconWindow.AttachDrawingObjectToWindow(lineObj);
            }
        }
        /// <summary>
        /// 获取模板数据
        /// </summary>
        /// <param name="path"></param>
        /// <param name="addres"></param>
        public void GetModelPaths()
        {
            string paths = path + "\\"+ this.form.Name+".json";
            //调用读取方法
            model1= HelpJsons.Read<double>(paths);
        }
        /// <summary>
        /// 设置模板数据
        /// </summary>
        /// <param name="path">工程文件名</param>
        /// <param name="addres">节点名</param>
        public void SetModelPaths()
        {

            string paths = path+"\\" + this.form.Name + ".json";
            if (!File.Exists(paths))
            {
                using (File.Create(paths)) { }
            }
            //调用存储方法
            HelpJsons.Write<double>(model1, paths);
        }
    }
}
